/*
 * File: gov.kdrm.mygset.util.DateTimeUtil.java
 *
 * Copyright (c) 2009 PT. XYBASE INDONESIA,
 * All Rights Reserved.
 *
 * This software is the confidential and proprietary information
 * of PT. XYBASE INDONESIA ("Confidential Information"). You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered
 * into with PT. XYBASE INDONESIA.
 *
 * Project:	mygset2
 * Created: Sep 24, 2009 2:00:00 PM
 */
package app.rci.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import app.rci.config.CommonConstants;

import java.sql.Time;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;

/**
 * <p>Common functions all about date and time</p>
 *
 * <p>Revision Information:<br/><i>
 * $Date: 2010-03-18 14:37:45 +0700 (Thu, 18 Mar 2010) $<br/>
 * $Revision: 22877 $
 * $LastChangedBy$
 * </i></p>
 *
 * @author Nia
 */
public abstract class DateTimeUtil {

	private static final Log log = LogFactory.getLog(DateTimeUtil.class);
	
	public static final String FORMAT_DATE = "dd/MM/yyyy";
	
	public static final String FORMAT_TIME = "HH:mm";
	

    /**
     * Get current date
     *
     * @return current date
     */
	public static String getCurrentDate() {
        DateFormat dateFormat = new SimpleDateFormat(CommonConstants.DATE_FORMAT);
        Date date = new Date();
        return dateFormat.format(date);
    }

    /**
     * Get current time
     *
     * @return current time
     */
	public static String getCurrentTime() {
        DateFormat dateFormat = new SimpleDateFormat(CommonConstants.TIME_FORMAT);
        Date date = new Date();
        return dateFormat.format(date);
    }

	
	public static java.sql.Date getCurrentServerSqlDate(){
        java.util.Date utilDate = new java.util.Date();
        java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
        return sqlDate;
    }
	
	
    /**
     * Format a Date object into String
     *
     * @param date the date
     * @param dateFormat format pattern
     * @return string of the formatted date
     */
	public static String formatDateToStr(Date date, String dateFormat) {
		String formattedDate = null;

		try {
			SimpleDateFormat formatter = new SimpleDateFormat(
                    dateFormat != null ? dateFormat : CommonConstants.DATE_FORMAT);
			formattedDate = formatter.format(date);
		} catch (Exception e) {
			log.error("Fail to format date.", e);
		}
		return formattedDate;
	}
	
	/**
     * This method to get formatted date
     * 
     * DatVT overload
     * @param date 
     * @return String with format: DD/MM/YYYY
     */
    public static String formatDateToStr(Date date) {
        String formattedDate = "";

        if(date == null){
            return formattedDate;
        }

        try {
            SimpleDateFormat formatter = new SimpleDateFormat(FORMAT_DATE);
            formattedDate = formatter.format(date);
        } catch (Exception e) {
            log.error("Fail to format date.", e);
        }
        return formattedDate;
    }

    /**
     * Convert a java.util.Date into java.sql.Date
     * @param dt the Date of java.util.Date
     * @return the Date of java.sql.Date
     */
	public static java.sql.Date formatDatetoSqlDate(Date dt) {
		return new java.sql.Date(dt.getTime());
	}

	
	public static java.sql.Date formatDatetoSqlDate(String strdt) {
        String DATE_FORMAT = "dd/MM/yyyy";
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
        java.sql.Date result = null;
        java.util.Date dt;

        if (!(strdt == null || strdt.length() == 0)) {

            try {
                dt = sdf.parse(strdt);
                result = new java.sql.Date(dt.getTime());
            } catch (java.text.ParseException e) {
                log.error("e" + e);
            }
        }

        log.debug("result" + result);

        return result;
    }
	
	
    /**
     * Convert a String of date into SQLDate
     *
     * @param strDate the date in string
     * @param format format pattern to parse
     * @return SQLDate of the input string
     */
	public static java.sql.Date convertStringToSQLDate(String strDate, String format){
	        try {
	        	if (strDate !=null && !"".equals(strDate.trim())){
	        		SimpleDateFormat sdf = new SimpleDateFormat(
                            format != null ? format : CommonConstants.DATE_FORMAT);
	        		return new java.sql.Date(sdf.parse(strDate).getTime());
	        	}
	        } catch (Exception e) {
	        	log.debug("Error convert to SQL Date" + e.getMessage());
	        }
	    return null;
	}

    /**
     * Convert and SQLDate into String
     *
     * @param dt        the SQLDate
     * @param format    format pattern
     * @return formatted SQLDate in String
     */
	public static String convertSQLDateToString(java.sql.Date dt, String format){
		if (dt != null){
			java.util.Date jDate = new java.util.Date(dt.getTime());
			try {
				return new SimpleDateFormat(
                        format != null ? format : CommonConstants.DATE_FORMAT).format(jDate);
			} catch (Exception pe) {
	        	log.debug("Error convert to String" + pe.getMessage());
	        }
		}
		return null;
	}

    /**
     * Generate list of Month
     * @return Map of month list
     */
	private static HashMap<String, String> getMonths()
	{
		HashMap<String, String> monthHashMap = new HashMap<String, String>();
		monthHashMap.put("01", "January");
		monthHashMap.put("02", "February");
		monthHashMap.put("03", "March");
		monthHashMap.put("04", "April");
		monthHashMap.put("05", "May");
		monthHashMap.put("06", "June");
		monthHashMap.put("07", "July");
		monthHashMap.put("08", "August");
		monthHashMap.put("09", "September");
		monthHashMap.put("10", "October");
		monthHashMap.put("11", "November");
		monthHashMap.put("12", "December");
		return monthHashMap;
	}

    /**
     * this method to get formatted time
     *
     * @param time          time to format
     * @param timeFormat    format pattern
     * @return formatted time
     */
	public static String formatTimeToStr(Time time, String timeFormat) {

		String formattedTime = "00:00";
		try {
			if (time != null) {
				SimpleDateFormat formatter = new SimpleDateFormat(
                        timeFormat != null ? timeFormat : CommonConstants.TIME_FORMAT_SHORT);
				formattedTime = formatter.format(time);
			}
		} catch (Exception e) {
			log.error("Fail to format date.", e);
		}
		return formattedTime;


	}

    /**
     * Convert a string of time format into Date
     * @param timeStr the time in string
     * @return Date
     */
	public static Date formatStrtoTime(String timeStr) {

		Date date = null;

        // Now if you have a string of time you can use a SimpleDateFormat
        // object to parse the string date and return a date object. The pattern
        // of the string should be passed to the simple date format constructor.
        // In the example below the string is formatted as hh:mm:ss (hour:minutes:
        // second).
        DateFormat sdf = new SimpleDateFormat(CommonConstants.TIME_FORMAT_SHORT);
        try
        {
            // The get the date object from the string just called the parse
            // method and pass the time string to it. The method throws ParseException
            // if the time string is in an invalid format. But remember as we don't
            // pass the date information this date object will represent the 1st of
            // january 1970.
            date = sdf.parse(timeStr);

            // As the parse process success we'll have our time string in the
            // created date instance.
            log.debug("Date and Time: " + date);
        } catch (Exception e) {
            e.printStackTrace();
        }

		return date;
	}

    /**
     * This method converts a String into a Date
     *
     * @param dtStr the date in string format
     * @return the Date
     */
    public static Date convertStringToDate(String dtStr) {

        if(Utils.isNullorEmptyString(dtStr)){
            return null;
        }

        Date date = null;
        SimpleDateFormat df = new SimpleDateFormat(CommonConstants.DATE_FORMAT);
        log.debug("Converting '" + dtStr + "' to date with format '" + CommonConstants.DATE_FORMAT + "'");
        try {
            date = df.parse(dtStr);
        } catch (ParseException pe) {
            log.error("Unable to conver a string to date" , pe);
        }
        return date;
    }
    
    /**
     * Convert from String number to String date
     * 
     * @author VuTrongDat
     * @param numberInput
     * @return String formated
     * @description example: 1201 -> 12 January
     */
    public static String convertNumberToDate(String numberInput)
    {
        if (numberInput==null)
        {
            return null;
        }
        else
        {
            int length = numberInput.length();
            if (length==0 || length >4)
            {
                return null;
            }
            else
            {               
                String tmpMonth = getMonths().get(numberInput.substring(length-2, length));
                if (tmpMonth==null)
                {
                    return null;
                }
                else
                {
                    String tmpDay =  numberInput.substring(0, length-2);
                    String tmpResult = tmpDay + " " + tmpMonth;
                    return tmpResult;
                }
            }           
        }
    }

    /**
     * This method using to check overlap between Start Date and End Date
     *
     * @param strStartDate the start date
     * @param strEndDate the end date
     * @return boolean value of whether the date is overlaped
     */
	public static boolean checkOverlapDate(String strStartDate, String strEndDate) {
	    Date startDate = convertStringToDate(strStartDate);
	    Date endDate = convertStringToDate(strEndDate);
	    if (startDate != null && endDate != null) {
	        log.debug("Compare " + strStartDate + " and " + strEndDate + ". Result = " + startDate.compareTo(endDate));
            return (startDate.compareTo(endDate) <= 0);
	    }
        return false;

	}

	/**
	 * This method check whether a key in date is later than current system date ot not.
     *
	 * @param strDate the date to check in string format
	 * @return True is the key in date in later than current date. False for otherwise.
	 */
	public static boolean isLaterThanCurrentDate(String strDate){
		Date keyinDate = convertStringToDate(strDate);
        return keyinDate != null && keyinDate.after(new Date());
    }

	/**
     * This function using to check whether string inputed is Date or not.
     * 
     * @author HaiVH
     * @param strDate
     * @return <code>true</code> if strDate is a date
     */
    public static boolean isValidDateStr(String strDate) {
        SimpleDateFormat df = new SimpleDateFormat(FORMAT_DATE);
        try {
            df.setLenient(false);
            df.parse(strDate);
        } catch (ParseException pe) {
            log.error("Unable to conver a string to date" , pe);
            return false;
        } catch (IllegalArgumentException e) {
            return false;
        }
        return true;
    }
    
    /**
     * This method check whether a key in date is later than current system date ot not.
     * @author John
     * @param strDate
     * @return True is the key in date in later than current date. False for otherwise.
     */
    public static boolean isLaterthanCurrentDate(String strDate){

        Date keyinDate = convertStringToDate(strDate);
        
        if(keyinDate!=null){
            return keyinDate.after(new Date());
        }
        
        return false;
    }
    
	/**
	 * To convert Date string (dd/mm/yyyy), time string (12hh:mi) and AM/PM to be a Timestamp.
     *
	 * @param dateStr Date string (dd/mm/yyyy)
	 * @param timestr time string (12hh:mi)
	 * @param ampm AM/PM
	 * @return Timestamp if all the pass in variables are valid otherwise null.
	 */
	public static Timestamp convertDateTimeToTimestamp(String dateStr, String timestr, String ampm){

		Timestamp timestamp = null;

		try {
			String[] dateString = dateStr.split("/");
			String[] timeString = timestr.split(":");
			if ("PM".equals(ampm)) {
				timeString[0] += 12;
			}
			Calendar cal = Calendar.getInstance();
			cal.set(Integer.parseInt(dateString[2]), Integer
					.parseInt(dateString[1]) - 1, Integer
					.parseInt(dateString[0]), Integer.parseInt(timeString[0]),
					Integer.parseInt(timeString[1]));
			timestamp = new Timestamp(cal.getTimeInMillis());
		} catch (Exception e) {
			timestamp = null;
		}
		return timestamp;
	}

	/**
	 * This method convert Date to String
     *
	 * @param inputDate Date
	 * @return strDate String (dd, Month yyyy)
	 */
	public static String converDatetoString(Date inputDate){
		String resultDate = "";
		String strDateTmp = "";
		try{
			strDateTmp = formatDateToStr(inputDate, CommonConstants.DATE_FORMAT);
		}catch (Exception e) {
			e.printStackTrace();
		}
		if (strDateTmp.length() > 0){
			String []arrDateTmp = strDateTmp.split("/");
			String dayTmp = arrDateTmp[0];
			String monthTmp = arrDateTmp[1];
			String month = getMonths().get(monthTmp);
			String yearTmp = arrDateTmp[2];
			resultDate = dayTmp + ", " + month + " " + yearTmp;
		}
		return resultDate;
	}
	
	/**
     * This method parses a timestamp value to a String type.
     *
     * @param timestamp The timestamp argument to be parsed as a String.
     * @param pattern
     * @return The value parsed as a String.
     */
    public static String convertTimestampToString(Timestamp timestamp) {
        if (timestamp != null) {
            SimpleDateFormat sdf = new SimpleDateFormat(CommonConstants.DATE_FORMAT);
            
            return sdf.format(timestamp);
        } else {
            return null;
        }
    }
    
	
}
